package com.flyqiu.flow.core;


import com.flyqiu.flow.api.FlyQiuFlowConfig;
import com.flyqiu.flow.api.cache.FlyQiuFlowCache;
import com.flyqiu.flow.api.candidate.FlowCandidateLoad;
import com.flyqiu.flow.api.deploy.IFlowDeploy;
import com.flyqiu.flow.api.event.FlowEngineEvent;
import com.flyqiu.flow.api.format.IBpmnFormat;
import com.flyqiu.flow.api.script.FlyQiuFlowScriptActuator;
import com.flyqiu.flow.api.std.FlyQiuFlowObjectFactory;
import com.flyqiu.flow.core.impl.DefaultFlowObjectFactory;
import com.flyqiu.flow.event.ActInstEvent;
import com.flyqiu.flow.event.ProcInstEvent;
import com.flyqiu.flow.event.UserTaskEvent;
import lombok.Getter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DefaultFlowConfigImpl implements FlyQiuFlowConfig {


    private FlyQiuFlowObjectFactory elementObjectFactory;

    private final List<FlowEngineEvent> procEngineEvents;

    private final List<ActInstEvent> actInstEvents;

    private final List<ProcInstEvent> procInstEvents;

    private final List<UserTaskEvent> userTaskEvents;

    private final List<IFlowDeploy> procDeploys;
    private final List<FlyQiuFlowCache> caches;

    private final List<IBpmnFormat> bpmnFormats;

    private final List<FlyQiuFlowScriptActuator> actuators;

    @Getter
    private final List<FlowCandidateLoad> candidateLoads;

    public DefaultFlowConfigImpl() {
        this(new DefaultFlowObjectFactory());
    }

    public DefaultFlowConfigImpl(FlyQiuFlowObjectFactory elementObjectFactory) {
        this.elementObjectFactory = elementObjectFactory;
        procEngineEvents = new ArrayList<>();
        actInstEvents = new ArrayList<>();
        procInstEvents = new ArrayList<>();
        userTaskEvents = new ArrayList<>();
        procDeploys = new ArrayList<>();
        caches = new ArrayList<>();
        bpmnFormats = new ArrayList<>();
        actuators = new ArrayList<>();
        candidateLoads = new ArrayList<>();

    }

    public void addCandidateLoad(FlowCandidateLoad candidateLoad) {
        if (candidateLoads.contains(candidateLoad)) {
            return;
        }
        candidateLoads.add(candidateLoad);
    }

    public void addBpmnFormat(IBpmnFormat bpmnFormat) {
        bpmnFormats.add(bpmnFormat);
    }

    public void addCache(FlyQiuFlowCache cache) {
        if (caches.contains(cache)) return;
        caches.add(cache);
    }

    @Override
    public List<FlyQiuFlowCache> getProcCaches() {
        return caches;
    }

    @Override
    public List<IBpmnFormat> getBpmnFormat() {
        return bpmnFormats;
    }

    @Override
    public List<FlyQiuFlowScriptActuator> getScriptActuators() {
        return actuators;
    }

    public void addScriptActuator(FlyQiuFlowScriptActuator flyQiuFlowScriptActuator) {
        if (actuators.contains(flyQiuFlowScriptActuator)) {
            return;
        }
        actuators.add(flyQiuFlowScriptActuator);
    }


    public void setElementObjectFactory(FlyQiuFlowObjectFactory elementObjectFactory) {
        this.elementObjectFactory = elementObjectFactory;
    }

    public void addEngineEvent(FlowEngineEvent... events) {
        if (events == null || events.length < 1) return;
        Arrays.stream(events).distinct().filter(e -> !procEngineEvents.contains(e)).forEach(procEngineEvents::add);
    }

    public void addActivityEvent(ActInstEvent... events) {
        if (events == null || events.length < 1) return;
        Arrays.stream(events).distinct().filter(e -> !actInstEvents.contains(e)).forEach(actInstEvents::add);
    }

    public void addInstEvents(ProcInstEvent... events) {
        if (events == null || events.length < 1) return;
        Arrays.stream(events).distinct().filter(e -> !procInstEvents.contains(e)).forEach(procInstEvents::add);
    }

    public void addTaskEvents(UserTaskEvent... events) {
        if (events == null || events.length < 1) return;
        Arrays.stream(events).distinct().filter(e -> !userTaskEvents.contains(e)).forEach(userTaskEvents::add);
    }

    public void addDeploys(IFlowDeploy... procDeploys) {
        Arrays.stream(procDeploys).distinct().filter(e -> !this.procDeploys.contains(e)).forEach(this.procDeploys::add);
    }


    @Override
    public FlyQiuFlowObjectFactory getElementObjectFactory() {
        return elementObjectFactory;
    }

    /**
     * 流程引擎事件
     *
     * @return
     */
    @Override
    public List<FlowEngineEvent> engineEvents() {
        return procEngineEvents;
    }

    /**
     * 流程活动事件
     *
     * @return
     */
    @Override
    public List<ActInstEvent> activityEvents() {
        return actInstEvents;
    }

    /**
     * 流程实例事件
     *
     * @return
     */
    @Override
    public List<ProcInstEvent> procInstEvents() {
        return procInstEvents;
    }

    /**
     * 用户任务事件
     *
     * @return
     */
    @Override
    public List<UserTaskEvent> userTaskEvents() {
        return userTaskEvents;
    }


}
